package com.rybbaby.tss.core.utils;

import org.apache.commons.lang.StringUtils;

import java.util.*;

/**
 * @description API接口签名工具类
 * @outhor xiejinwei
 * @create 2017-12-14 11:39
 */
public class SignUtil {

    /**
     * 验证签名
     *
     * @param paramsMap 需要签名的参数键值对
     * @param timestamp 时间戳
     * @param randomStr 随机字符串
     * @param sign      需要验证的签名
     * @return
     */
    public static boolean validateSign(Map<String, Object> paramsMap, long timestamp, String randomStr, String sign) {
        return genSign(paramsMap, timestamp, randomStr).equals(sign);
    }

    /**
     * 生成签名
     * 生成规则：
     * 1、把除时间戳（timestamp）、随机字符串(randomStr)之外的所有参数按参数的key自然顺序排序
     * 2、根据排序完的key,将所有参数组装成如下格式的字符串：timestamp=客户端传入的timestamp&key1=value1&key2=value2&key3=value3.....&randomStr=客户端传入的randomStr,这一步得到字符串:str1
     * 3、将拼成的字符串str1全部转换成小写,得到字符串：str2
     * 4、将转换成的小写之后的字符串str2倒序,得到字符串：str3
     * 5、组合需要即将生成签名的字符串，格式：客户端传入的timestamp+第四步得到的str3+客户端传入的randomStr，这一步得到字符串：str4
     * 6、生成签名：使用标准MD5加密第5步获取到的字符串str4,这一步得到的32位字符串将是签名结果
     *
     * @param paramsMap 需要签名的参数键值对
     * @param timestamp 时间戳
     * @param randomStr 随机字符串
     * @return
     */
    public static String genSign(Map<String, Object> paramsMap, long timestamp, String randomStr) {
        List<String> sortedParamList = new ArrayList<>();
        //参数自然顺序排序
        List<String> sortedKeys = Arrays.asList(StringUtils.split(StringUtils.join(paramsMap.keySet(), ","), ","));
        Collections.sort(sortedKeys);
        //组装排序后的参数字符串
        sortedParamList.add("timestamp=" + timestamp);//时间戳放在开头
        for (String key : sortedKeys) {
            sortedParamList.add(key + "=" + paramsMap.get(key));
        }
        sortedParamList.add("randomStr=" + randomStr);//随机字符串放在末尾
        String sortedParamStr = StringUtils.reverse(StringUtils.lowerCase(StringUtils.join(sortedParamList, "&")));//全部转换成小写并倒序
        //生成签名
        return MD5Util.getMD5String(new StringBuffer().append(timestamp).append(sortedParamStr).append(randomStr).toString());
    }

}
